package com.thoughtworks.studio.tools.cardkit.parser;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

import org.apache.log4j.Logger;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;

import com.thoughtworks.studio.tools.cardkit.Card;

public class ExcelParser implements CardParser {
	private HSSFWorkbook workbook;
	private Logger logger = Logger.getLogger(ExcelParser.class);
	private List<List<Object>> cardMatrix;
	private Map<Float,Card> cards = null;

	public ExcelParser() {
	}

	public List<List<Object>> getDatasInSheet(int sheetNumber)
			throws FileNotFoundException, IOException {
		List<List<Object>> result = new ArrayList<List<Object>>();

		HSSFSheet sheet = workbook.getSheetAt(sheetNumber);

		int rowCount = sheet.getLastRowNum();
		if (rowCount < 1) {
			return result;
		}
		for (int rowIndex = 0; rowIndex <= rowCount; rowIndex++) {

			HSSFRow row = sheet.getRow(rowIndex);

			if (row != null) {
				List<Object> rowData = new ArrayList<Object>();
				int columnCount = row.getLastCellNum();
				logger.debug("excel columnCount= " + columnCount);
				for (short columnIndex = 0; columnIndex < columnCount; columnIndex++) {
					HSSFCell cell = row.getCell(columnIndex);
					Object cellStr = this.getCellString(cell);
					rowData.add(cellStr);
				}
				result.add(rowData);
			}
		}
		return result;
	}

	protected Object getCellString(HSSFCell cell) {
		Object result = null;
		if (cell != null) {

			int cellType = cell.getCellType();

			switch (cellType) {

			case HSSFCell.CELL_TYPE_STRING:
				result = cell.getRichStringCellValue().getString();
				break;
			case HSSFCell.CELL_TYPE_NUMERIC:
				result = cell.getNumericCellValue();
				break;
			case HSSFCell.CELL_TYPE_FORMULA:
				result = cell.getNumericCellValue();
				break;
			case HSSFCell.CELL_TYPE_ERROR:
				result = null;
				break;
			case HSSFCell.CELL_TYPE_BOOLEAN:
				result = cell.getBooleanCellValue();
				break;
			case HSSFCell.CELL_TYPE_BLANK:
				result = null;
				break;
			}
		}

		return result == null ? "" : result;
	}

	public void parse(String excelfilename) throws FileNotFoundException,
			IOException {
		if (!excelfilename.endsWith(".xls")) {
			logger.error("the file " + excelfilename + "is not a excel fiile.");
			throw new FileNotFoundException();
		}
		File excelfile = new File(excelfilename);
		if (!excelfile.exists()) {
			throw new FileNotFoundException();
		}
		workbook = new HSSFWorkbook(new FileInputStream(excelfile));
		cardMatrix = getDatasInSheet(0);
		convertMatrixToCards();
		
	}

	private void convertMatrixToCards() {
		cards = new TreeMap<Float,Card>();
		List<Object> prop = (List<Object>) cardMatrix.get(0);
		String eachProp = null;
		Object eachValue = null;

		for (int i = 1; i < cardMatrix.size(); i++) {
			Card card = new Card();
			List<Object> rowdata = cardMatrix.get(i);

			for (int j = 0; j < rowdata.size() - 1; j++) {
				eachProp = (String) prop.get(j);
				eachValue = rowdata.get(j) == null ? "" : rowdata.get(j);
				card.setPorperty(eachProp, eachValue);
				String value = String.valueOf(eachValue);
				if (eachProp.equals("Number"))
					card.setNumber(Float.parseFloat( value ));
				if (eachProp.equals("Name"))
					card.setName(String.valueOf(eachValue));
			}
			cards.put(card.getNumber(),card);
		}
	}

	public Map<Float,Card> getCards() throws ParserException{
		if (cards == null) {
			throw new ParserException("Parse failed! Please check the excel file for the cards.");
		}
		return cards;
	}
}
